home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD Concept 6
/
CD Concept 06.iso
/
mac
/
UTILITAIRE
/
Little Smalltalk v3.1.4
/
C Source
/
Sources
/
glue2.cp
< prev
next >
Wrap
Text File
|
1995-01-26
|
23KB
|
777 lines
/*
Little Smalltalk, version 3
Written by Tim Budd, Oregon State University, June 1988
Symantec Think Class Library interface code
⌐Julian Barkway, April 1994, all rights reserved.
glue2.cp
--------
This is the interface between Little Smalltalk and the Symantec Think
Class Library (v1.1.3). Where possible, I have retained the StdWin
function names and parameters used in the original Little Smalltalk (v3)
(although certain structures now refer to TCL objects) in order to assist
porting.
Glue1.cp contains functions relating to windows, menus, graphics and dialogues.
Glue2.cp contains text, event handling and general purpose functions.
*/
#include <string.h>
#include "env.h"
#include "memory.h"
#include "macio.h"
#undef class
#include "Constants.h"
#include "CDataFile.h"
#include "CGraphicsPane.h"
#include "CTextPane.h"
#include "CSelectPane.h"
#include "CLStWindow.h"
#include "CLStApp.h"
#include "CLStSwitchboard.h"
#include "CLStScrollPane.h"
#include "LStResources.h"
#include "glue.h"
extern short gClicks;
extern CLStApp *gSmalltalk;
#define uchar unsigned char // Just laziness :-)
//===================================================================================
// Set the font in the given TextEdit to the font specified in fontName.
// Not a StdWin function.
//===================================================================================
void setFont (TEXTEDIT *tp, char *fontName)
{
Str255 str;
Rect margin = {0, 0, 0, 0};
strcpy ((char *)str, fontName);
CtoPstr ((char *)str);
((CTextPane *)tp)->SetFontName (str);
// Force a dummy re-size which will re-calculate number
// of complete lines available, thereby ensuring that
// the last line doesn't get clipped vertically.
((CTextPane *)tp)->ResizeFrame (&margin);
((CTextPane *)tp)->AdjustBounds ();
}
//===================================================================================
// Set the font size in the given TextEdit to that specified by fontSize.
// Not a StdWin function.
//===================================================================================
void setFontSize (TEXTEDIT *tp, short fontSize)
{
Rect margin = {0, 0, 0, 0};
((CTextPane *)tp)->SetFontSize (fontSize);
((CTextPane *)tp)->ResizeFrame (&margin);
((CTextPane *)tp)->AdjustBounds ();
}
//===================================================================================
// Set the type face in the given TextEdit to that specified by typeFace.
//
// Note that in Smalltalk the following faces are available:
// 1 - plain,
// 2 - bold,
// 3 - italic,
// 4 - underline
//
// and are specified by the numbers given NOT the Mac system constants.
//
// Not a StdWin function.
//===================================================================================
void setTypeFace (TEXTEDIT *tp, short typeFace)
{
Rect margin = {0, 0, 0, 0};
switch (typeFace) {
case 1:
typeFace = normal;
break;
case 2:
typeFace = bold;
break;
case 3:
typeFace = italic;
break;
case 4:
typeFace = underline;
break;
default:
typeFace = normal;
}
((CTextPane *)tp)->SetFontStyle (typeFace);
((CTextPane *)tp)->ResizeFrame (&margin);
((CTextPane *)tp)->AdjustBounds ();
}
//===================================================================================
// Replace the currently selected text in the given TextEdit by the text specified.
//===================================================================================
void tereplace (TEXTEDIT *tp, char *str)
{
short i;
long selStart, selEnd;
TEHandle teh = ((CTextPane *)tp)->macTE;
for (i = 0; i < strlen (str); i++) // Convert all LFs to CRs
if (str [i] == '\n') // -- probably unnecessary in majority of cases.
str [i] = '\r';
((CTextPane *)tp)->GetSelection (&selStart, &selEnd);
if (selEnd > selStart) {
((CTextPane *)tp)->SetSelection (selEnd, selEnd, FALSE);
}
((CTextPane *)tp)->InsertTextPtr ((Ptr)str, (long)strlen (str), TRUE);
((CTextPane *)tp)->AdjustBounds ();
}
//===================================================================================
// Replace all the text in a text pane with the given text. Not a StdWin function.
//===================================================================================
void replaceAllText (TEXTEDIT *tp, char *str)
{
short i;
for (i = 0; i < strlen (str); i++) // Convert all LFs to CRs
if (str [i] == '\n')
str [i] = '\r';
((CTextPane *)tp)->ReplaceContents (str);
((CTextPane *)tp)->AdjustBounds ();
}
//===================================================================================
// Delete all the text in a text pane. Not a StdWin function.
//===================================================================================
void deleteAllText (TEXTEDIT *tp)
{
((CTextPane *)tp)->DeleteContents ();
((CTextPane *)tp)->AdjustBounds ();
}
//===================================================================================
// Return current size of pane. Not a StdWin function.
//===================================================================================
void getPaneSize (TEXTEDIT *tp, short *width, short *height)
{
long w, h;
((CPane *)tp)->GetPixelExtent (&w, &h);
*width = (short)w;
*height = (short)h;
}
#define getSizingOptions(x,y,x1,y1) if (x) \
x1 = sizELASTIC; \
else \
x1 = sizFIXEDLEFT; \
if (y) \
y1 = sizELASTIC; \
else \
y1 = sizFIXEDLEFT
//===================================================================================
// Add a basic pane to a window - not a StdWin function.
//===================================================================================
TEXTEDIT *addScrollPane (WINDOW *win, short left, short top, short right, short bottom,
short horizOption, short vertOption)
{
CLStScrollPane *scrollPane;
short w = right - left,
h = bottom - top;
scrollPane = new (CLStScrollPane);
scrollPane->IScrollPane ((CLStWindow *)win->window, (CDocument *)(win->document),
w, h, left, top,
(SizingOption)horizOption, (SizingOption)vertOption,
TRUE, TRUE, TRUE);
return (char *)scrollPane;
}
//===================================================================================
// Add a selection pane to a window - not a StdWin function.
//===================================================================================
TEXTEDIT *addSelPane (WINDOW *win, short left, short top, short right, short bottom,
short horizElastic, short vertElastic, short lineLength)
{
CSelectPane *selPane;
CLStScrollPane *scrollPane;
LongPt origin = {0L, 0L};
SizingOption horizOption, vertOption;
getSizingOptions (horizElastic, vertElastic, horizOption, vertOption);
scrollPane = (CLStScrollPane *)addScrollPane (win, left, top, right, bottom,
horizOption, vertOption);
selPane = new (CSelectPane);
selPane->ISelectPane (scrollPane, (CDocument *)(win->document),
horizOption, vertOption, lineLength);
((CDocument *)(win->document))->itsMainPane = selPane;
((CDocument *)(win->document))->itsGopher = selPane;
scrollPane->InstallPanorama (selPane);
selPane->ScrollTo (&origin, TRUE); // Ensure everything is visible
return (char *)selPane;
}
//===================================================================================
// Add a text pane to a window
//===================================================================================
TEXTEDIT *addTextPane (WINDOW *win, short left, short top, short right, short bottom,
short horizElastic, short vertElastic, short lineLength)
{
CTextPane *textPane;
CLStScrollPane *scrollPane;
LongPt origin = {0L, 0L};
SizingOption horizOption, vertOption;
getSizingOptions (horizElastic, vertElastic, horizOption, vertOption);
scrollPane = (CLStScrollPane *)addScrollPane (win, left, top, right, bottom,
horizOption, vertOption);
textPane = new (CTextPane);
textPane->ITextPane (scrollPane, (CDocument *)(win->document),
horizOption, vertOption, lineLength);
((CDocument *)(win->document))->itsMainPane = textPane;
((CDocument *)(win->document))->itsGopher = textPane;
scrollPane->InstallPanorama (textPane);
textPane->ScrollTo (&origin, TRUE); // Ensure everything is visible
return (char *)textPane;
}
//===================================================================================
// Stub function provided for StdWin compatibility.
//===================================================================================
TEXTEDIT *tecreate (WINDOW *win, int left, int top, int right, int bottom)
{
return addTextPane (win, left, top, right, bottom, TRUE, TRUE, 2000);
}
//===================================================================================
// Add a graphics pane to a window
//===================================================================================
TEXTEDIT *addGraphicsPane (WINDOW *win, short left, short top, short right, short bottom,
short horizElastic, short vertElastic)
{
CGraphicsPane *gPane;
CLStScrollPane *scrollPane;
LongPt origin = {0L, 0L};
SizingOption horizOption, vertOption;
getSizingOptions (horizElastic, vertElastic, horizOption, vertOption);
scrollPane = (CLStScrollPane *)addScrollPane (win, left, top, right, bottom,
horizOption, vertOption);
gPane = new (CGraphicsPane);
gPane->IGraphicsPane (scrollPane, (CDocument *)(win->document),
horizOption, vertOption);
((CDocument *)(win->document))->itsMainPane = gPane;
((CDocument *)(win->document))->itsGopher = gPane;
scrollPane->InstallPanorama (gPane);
gPane->ScrollTo (&origin, TRUE); // Ensure everything is visible
return (char *)gPane;
}
//===================================================================================
// Stub function provided for StdWin compatibility.
//===================================================================================
Boolean teevent (TEXTEDIT *tp, EVENT *e)
{
return FALSE;
}
//===================================================================================
// Scroll the text, if necessary, to ensure that the selected area is visible in the
// text pane.
//===================================================================================
void scrollToSelection (TEXTEDIT *tp)
{
((CTextPane *)tp)->ScrollToSelection ();
}
//===================================================================================
// Set the text selection to the given character positions.
//===================================================================================
void setTextSelection (TEXTEDIT *tp, long startPos, long endPos)
{
((CTextPane *)tp)->SetSelection (startPos, endPos, TRUE);
}
//===================================================================================
// Return the start and end character positions of the current text selection.
//===================================================================================
void getTextSelection (TEXTEDIT *tp, long *startPos, long *endPos)
{
((CTextPane *)tp)->GetSelection (startPos, endPos);
}
//===================================================================================
// tegettext - return all the text associated with the current TE.
//===================================================================================
#define MAXBUF 8 * 1024
uchar buf [MAXBUF];
char *tegettext (TEXTEDIT *tp)
{
Handle th;
short i, j;
long maxText;
maxText = ((CTextPane *)tp)->GetLength ();
th = ((CTextPane *)tp)->GetTextHandle ();
if (maxText > MAXBUF - 1)
maxText = MAXBUF - 1;
BlockMove (*th, buf, maxText);
buf [maxText] = '\0';
return (char *)buf;
}
//===================================================================================
// Return the text inside the selected area (if there is any)
// Not a StdWin function.
//===================================================================================
char *teGetSelectedText (TEXTEDIT *tp)
{
long selStart, selEnd;
short i;
char *cp;
cp = (char *)*(((CTextPane *)tp)->GetTextHandle ());
((CTextPane *)tp)->GetSelection (&selStart, &selEnd);
if (selEnd <= selStart) {
buf [0] = '\0';
return (char *)buf;
}
for (i = 0; i < MAXBUF; i++) {
if (selStart == selEnd)
break;
buf [i] = cp [selStart++];
}
buf [i] = '\0';
return (char *)buf;
}
//===================================================================================
// Draw the contents of the given TextEdit.
//===================================================================================
void tedraw (register TEXTEDIT *tp)
{
Rect area;
LongRect lr, margin = {0, 0, 0, 0};
((CTextPane *)tp)->GetAperture (&lr);
((CTextPane *)tp)->FrameToQDR (&lr, &area);
((CTextPane *)tp)->Draw (&area);
}
//===================================================================================
// Save the text of a TextEdit to the given file. Not a StdWin function.
//===================================================================================
void saveTE (TEXTEDIT *tp, short fileNum)
{
CDataFile *fil;
FILE *fd;
CharsHandle teh;
teh = TEGetText (((CTextPane *)tp)->macTE);
fil = new (CDataFile);
fil->IDataFile ();
fd = getFilePointer (fileNum);
fil->refNum = fd->fileRef;
fil->WriteAll ((Handle)teh);
}
//===================================================================================
// Load the text of a TextEdit from the given file. Not a StdWin function.
//===================================================================================
void loadTE (TEXTEDIT *tp, short fileNum)
{
CDataFile *fil;
FILE *fd;
Handle hndl;
fil = new (CDataFile);
fil->IDataFile ();
fd = getFilePointer (fileNum);
fil->refNum = fd->fileRef;
hndl = fil->ReadAll ();
((CTextPane *)tp)->ReplaceContents ((char *)*hndl);
((CTextPane *)tp)->AdjustBounds ();
}
//===================================================================================
// Send an Open Document AppleEvent to the specified app using the specified file.
// Not a StdWin function.
//===================================================================================
OSErr sendOpenDocEvent (long theAppSig, SFReply *theSFReply)
{
AppleEvent aEvent;
FSSpec theFile;
WDPBRec wdInfo;
OSErr err;
AEDescList docList;
AEDesc docDesc, sigDesc;
AERecord aeRec;
Boolean disposeCheck [4] = {FALSE, FALSE, FALSE, FALSE};
err = AECreateDesc (typeApplSignature, &theAppSig, (Size)sizeof(long),
&sigDesc);
if (err)
goto sendOpenDocEvent_exit;
disposeCheck [0] = TRUE;
err = AECreateAppleEvent (kCoreEventClass, kAEOpenDocuments, &sigDesc,
kAutoGenerateReturnID, kAnyTransactionID, &aEvent);
if (err)
goto sendOpenDocEvent_exit;
disposeCheck [1] = TRUE;
wdInfo.ioNamePtr = NULL; // Convert SFReply to FSSpec
wdInfo.ioVRefNum = theSFReply->vRefNum;
wdInfo.ioWDIndex = 0;
wdInfo.ioWDProcID = 0;
err = PBGetWDInfo (&wdInfo, FALSE);
if (err)
goto sendOpenDocEvent_exit;
theFile.vRefNum = wdInfo.ioWDVRefNum;
theFile.parID = wdInfo.ioWDDirID;
BlockMove (theSFReply->fName, theFile.name, (long)theSFReply->fName [0] + 1);
err = AECreateList (NULL, 0, FALSE, &docList);
if (err)
goto sendOpenDocEvent_exit;
disposeCheck [2] = TRUE;
err = AECreateDesc (typeFSS, &theFile, (Size)sizeof (FSSpec), &docDesc);
if (err)
goto sendOpenDocEvent_exit;
disposeCheck [3] = TRUE;
err = AEPutDesc (&docList, 0L, &docDesc);
if (err)
goto sendOpenDocEvent_exit;
err = AEPutParamDesc (&aEvent, keyDirectObject, &docList);
if (err)
goto sendOpenDocEvent_exit;
err = AESend (&aEvent, NULL, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
sendOpenDocEvent_exit:
if (disposeCheck [1])
AEDisposeDesc (&aEvent);
if (disposeCheck [2])
AEDisposeDesc (&docList);
if (disposeCheck [3])
AEDisposeDesc (&docDesc);
if (err)
return err;
return 0L;
}
//===================================================================================
// Translate the info provided after an Open Document event has been received into
// the full path and file type that Smalltalk currently likes. (I really will have
// to get Smalltalk used to dealing with directory IDs one of these days...) Return
// FALSE if info not present.
//
// Not a StdWin function.
//===================================================================================
Boolean getFileInfo (char *fullPath, long *fType)
{
if (gSmalltalk->theFile.fType == 0L)
return FALSE;
*fType = (long)gSmalltalk->theFile.fType;
getPathNameFromWD ((long)gSmalltalk->theFile.vRefNum, fullPath);
PtoCstr (gSmalltalk->theFile.fName);
strcat (fullPath, (char *)gSmalltalk->theFile.fName);
CtoPstr ((char *)gSmalltalk->theFile.fName);
return TRUE;
}
//===================================================================================
// Process any AppleEvents sent by the Finder when the application is first launched.
// I handle these separately from other events so I can load a system image before
// Smalltalk itself is started.
//
// Only HighLevelEvents are processed; anything else is ignored.
//
// Not a StdWin function.
//===================================================================================
Boolean processStartUpEvent (char *buf)
{
EventRecord event;
long fType;
short i = 255;
OSErr err;
while (i) {
if (WaitNextEvent (highLevelEventMask, &event, 0, NULL) ) {
if (AEProcessAppleEvent (&event))
return FALSE; // Error case.
if (getFileInfo (buf, &fType)) {
if (fType == kSysImageType)
return TRUE;
else { // Not a sys. image so requeue Event for handling later
err = sendOpenDocEvent (kCreator, &gSmalltalk->theFile);
return FALSE;
}
}
}
i--;
}
}
//===================================================================================
// Get a user event from the system and translate it into StdWin format.
//===================================================================================
Point lastMouse = {-32767, -32767};
void wgetevent (EVENT *ep)
{
EventRecord *macEvent;
Point wp;
char theChar;
Byte keyCode;
WindowPtr w;
gSmalltalk->lastEvent.what = 0;
gSmalltalk->theFile.fType = 0L;
gSmalltalk->Process1Event ();
if (gSmalltalk->menuID == 0xffff) {
ep->type = WE_QUIT;
return;
}
if (gSmalltalk->lastEvent.what == 0) {
ep->type = WE_NULL;
return;
}
macEvent = &(gSmalltalk->lastEvent);
wp = macEvent->where;
GlobalToLocal (&wp);
if (lastMouse.h == -32767 && lastMouse.v == -32767)
lastMouse = wp;
w = FrontWindow ();
if (w)
ep->window = ((CLStWindow *)GetWRefCon (w))->theLStWindow;
else
ep->window = NULL;
switch (macEvent->what) {
case mouseDown:
processMouseDown (macEvent, ep);
break;
case mouseUp:
ep->type = WE_MOUSE_UP;
ep->u.where.h = wp.h;
ep->u.where.v = wp.v;
ep->u.where.clicks = 1;
ep->u.where.button = 1;
ep->u.where.mask = 0;
break;
case keyDown:
case autoKey:
theChar = macEvent->message & charCodeMask;
keyCode = (macEvent->message & keyCodeMask) >> 8;
if (macEvent->modifiers & cmdKey)
break;
switch (keyCode) {
case kEscapeOrClear:
case kLeftCursor:
case kRightCursor:
case kUpCursor:
case kDownCursor:
case KeyHome:
case KeyEnd:
case KeyPageUp:
case KeyPageDown:
case KeyEscape:
case KeyClear:
case KeyHelp:
case KeyFwdDelete:
case KeyF1:
case KeyF2:
case KeyF3:
case KeyF4:
case KeyF5:
case KeyF6:
case KeyF7:
case KeyF8:
case KeyF9:
case KeyF10:
case KeyF11:
case KeyF12:
case KeyF13:
case KeyF14:
case KeyF15:
ep->type = WE_KEY;
ep->u.key.code = keyCode;
ep->u.key.mask = WM_META;
break;
case KeyLeftCursor:
case KeyRightCursor:
case KeyUpCursor:
case KeyDownCursor:
ep->type = WE_COMMAND;
ep->u.command = WC_LEFT;
break;
case kEnterKey:
ep->type = WE_COMMAND;
ep->u.command = WC_RETURN;
break;
default:
ep->type = WE_CHAR;
ep->u.character = theChar;
}
break;
case updateEvt:
{
WindowPtr w = FrontWindow ();
Rect r = (**(((WindowRecord *)w)->updateRgn)).rgnBBox;
ep->type = WE_DRAW;
ep->u.area.left = r.left;
ep->u.area.top = r.top;
ep->u.area.right = r.right;
ep->u.area.bottom = r.bottom;
break;
}
case activateEvt:
ep->type = WE_ACTIVATE;
break;
case kHighLevelEvent: /* Process AppleEvent */
ep->type = WE_EXTERN;
break;
default:
if ( (wp.h != lastMouse.h)
|| (wp.v != lastMouse.v) ) {
ep->type = WE_MOUSE_MOVE;
ep->u.where.h = wp.h;
ep->u.where.v = wp.v;
lastMouse = wp;
ep->u.where.clicks = gClicks;
ep->u.where.button = 1;
ep->u.where.mask = 0;
}
else
ep->type = WE_NULL;
}
lastMouse = wp;
}
//===================================================================================
// Special processing for mouseDown events. Not a StdWin function.
//===================================================================================
void processMouseDown (EventRecord *macEvent, EVENT *ep)
{
if (gSmalltalk->winPart != inContent && gSmalltalk->winPart == inSysWindow)
return;
switch (gSmalltalk->winPart) {
case inMenuBar:
ep->type = WE_MENU;
if (gSmalltalk->menuID > kSTMenuBase) {
ep->u.m.id = gSmalltalk->menuID - kSTMenuBase;
ep->u.m.item = gSmalltalk->menuItem - 1;
}
else {
ep->type = WE_NULL;
ep->u.m.id = 0;
ep->u.m.item = 0;
}
break;
case inDrag:
ep->type = WE_MOVE;
break;
case inGrow:
ep->type = WE_SIZE;
break;
case inGoAway:
ep->type = WE_CLOSE;
break;
default:
{
WINDOW *w;
GrafPtr aPort;
ep->type = WE_MOUSE_DOWN;
if (ep->window != NULL)
((CLStWindow *)(ep->window->window))->Prepare ();
GlobalToLocal (&(macEvent->where)); // Return point in _window_ co-ords.
ep->u.where.h = macEvent->where.h;
ep->u.where.v = macEvent->where.v;
ep->u.where.clicks = gClicks;
if (macEvent->modifiers & optionKey)
ep->u.where.button = 2; // Simulate a 2 button mouse with help of 'option' key
else
ep->u.where.button = 1;
ep->u.where.mask = 0;
}
}
}
//===================================================================================
// Stub function provided for StdWin compatibility.
//===================================================================================
void wsettimer (WINDOW *win, int deciseconds)
{
return;
}